#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <queue>

using namespace std;

class threadname
{
public:
	string _name;       //线程的名字
	pthread_t tid;      //线程的tid
};

template <class T>
class Threadpool
{
private:
    //加锁
	void Lock()
	{
		pthread_mutex_lock(&_mutex);
	}
    
	//解锁
	void Unlock()
	{
		pthread_mutex_unlock(&_mutex);
	}
    
	//线程等待
	void Wait()
	{
		pthread_cond_wait(&_cond, &_mutex);
	}
    
	//唤醒线程
	void signal()
	{
		pthread_cond_signal(&_cond);
	}
    
	//输出线程的名字
	string Getthreadname(pthread_t tid)
	{
		for (auto ti : _v)
		{
			if (ti.tid == tid)
			{
				return ti._name;
			}
		}
		return nullptr;
	}

public:
    //构造函数
	Threadpool(int max = 10)
		: _max(max), _v(max)                        //初始化数组和_max
	{
		pthread_mutex_init(&_mutex, nullptr);       //初始化锁
		pthread_cond_init(&_cond, nullptr);         //初始化条件变量
	}

	static void *hander(void *args)
	{
		Threadpool<T> *td = static_cast<Threadpool<T> *>(args);
		string name = td->Getthreadname(pthread_self());     //通过tid，将该线程的名字从数组中拿出

		while (true)
		{
			td->Lock();
			while (td->_q.empty())       //队列如果为空，则进行线程等待
			{
				td->Wait();
			}

			T t = td->pop();             //将任务从队列中拿出
			td->Unlock();
			t.run();

			cout << name << " a result:" << t.GetResult() << endl;
		}
	}
    
	//创造线程
	void Create()
	{

		int num = _v.size();
		for (int i = 0; i < num; i++)
		{
			_v[i]._name = "thread_" + to_string(i + 1);   //将线程的名字存入数组中
			pthread_create(&(_v[i].tid), nullptr, hander, (void *)this);
			cout<<_v[i]._name<<endl;                      //打印创造的线程名字
		}
		
	}
    
	//将任务添加到队列中
	void push(T &data)
	{
		Lock();
		_q.push(data);
		cout << "thread produser a task:" << data.GetTask() << endl;
		signal();
		Unlock();
	}
    
	//从队列中拿出任务
	T pop()
	{
		T t = _q.front();
		_q.pop();
		return t;
	}
    
	//析构函数
	~Threadpool()
	{
		pthread_mutex_destroy(&_mutex);
		pthread_cond_destroy(&_cond);
	}

private:
	vector<threadname> _v;    //定义一个数组，用来存放线程的名字和tid
	queue<T> _q;              //队列，用来存放任务
	int _max;	              // 数组的大小

	pthread_mutex_t _mutex;   // 锁
	pthread_cond_t _cond;     
};
